package com.qingzhuge.manager.controller;

import com.qingzhuge.common.annotation.ASysLog;
import com.qingzhuge.common.enums.EAuthorityType;
import com.qingzhuge.common.enums.EResourceType;
import com.qingzhuge.core.annotation.AResource;
import com.qingzhuge.dto.response.ResponseBodyDto;
import com.qingzhuge.exception.ServiceException;
import com.qingzhuge.manager.controller.base.BaseUidPkLongController;
import com.qingzhuge.manager.service.ISysUserService;
import com.qingzhuge.resource.dto.request.SysResourceRequestDto;
import com.qingzhuge.resource.dto.response.SysResourceResponseDto;
import com.qingzhuge.resource.entity.SysResource;
import com.qingzhuge.resource.service.ISysResourceService;
import com.qingzhuge.resource.vo.TreeVo;
import com.qingzhuge.utils.PageUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.constraints.NotBlank;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

import static com.qingzhuge.common.Constants.Controller.PATH_LIST;

/**
 * @author : zero.xiao
 * @description : 系统菜单
 * @date :2018/6/8 0008 下午 14:50
 * @modified :
 */
@ASysLog(value = "系统菜单")
@Api(tags = "S菜单管理")
@AResource(name = "菜单管理", type = EResourceType.menu, catalog = "系统管理")
@RestController
@RequestMapping(value = "api/sys/auth/menu")
public class SysResourceController extends BaseUidPkLongController<
        SysResource, ISysResourceService, SysResourceRequestDto, SysResourceResponseDto> {
    @Resource
    private ISysUserService userService;

    /**
     * 导航菜单
     */
    @GetMapping(value = "nav")
    public ResponseEntity<ResponseBodyDto<Collection<SysResource>>> nav() {
        Collection<SysResource> resourceList = userService.queryResourceByUid(getUserId());
        return returnSuccess(resourceList);
    }

    @Override
    public ResponseEntity<ResponseBodyDto<PageUtil<SysResourceResponseDto>>> queryPage(@RequestBody(required = false) SysResourceRequestDto param) {
        return super.queryPage(param);
    }

    @GetMapping(PATH_LIST)
    @ApiOperation(value = "列表")
    @AResource(type = EResourceType.button, authority = EAuthorityType.READ, name = "列表")
    public ResponseEntity<ResponseBodyDto<List<TreeVo>>> treeList() {
        List<TreeVo> resList = service.queryTreeListByParent(null);
        return returnSuccess(resList);
    }

    @Override
    public ResponseEntity<ResponseBodyDto<SysResourceResponseDto>> get(@PathVariable Long id) {
        return super.get(id);
    }

    @Override
    public ResponseEntity<ResponseBodyDto<SysResourceResponseDto>> save(@RequestBody SysResourceRequestDto resource) {
        //数据校验
        verifyForm(resource);
        return super.save(resource);
    }

    @Override
    public ResponseEntity<ResponseBodyDto<SysResourceResponseDto>> update(@RequestBody SysResourceRequestDto resource) {
        //数据校验
        verifyForm(resource);
        return super.update(resource);
    }

    @Override
    public ResponseEntity<ResponseBodyDto<Object>> delete(@PathVariable @NotBlank Long id) {
        if (id <= 1) {
            return returnFailed("系统菜单，不能删除");
        }
        //判断是否有子菜单或按钮
        List<SysResource> resourceList = service.queryListByParent(new SysResource(id));
        if (resourceList.size() > 0) {
            return returnFailed("请先删除子菜单或按钮");
        }
        return super.delete(id);
    }

    /**
     * 验证参数是否正确
     */
    private void verifyForm(SysResourceRequestDto resource) {
        if (StringUtils.isBlank(resource.getName())) {
            throw new ServiceException("菜单名称不能为空");
        }

        if (resource.getParent() == null) {
            throw new ServiceException("上级菜单不能为空");
        }

        //菜单
        EResourceType resourceType = resource.getType();
        EResourceType menuValue = EResourceType.menu;
        EResourceType catalogValue = EResourceType.catalog;
        EResourceType buttonValue = EResourceType.button;
        EResourceType apiValue = EResourceType.api;
        EResourceType apicatalogValue = EResourceType.apicatalog;
        if (Objects.equals(resourceType, menuValue)) {
            if (StringUtils.isBlank(resource.getUrl())) {
                throw new ServiceException("菜单URL不能为空");
            }
        }

        //上级菜单类型
        EResourceType parentType = getResourceType(resource, catalogValue);

        //目录、菜单
        if (Objects.equals(resourceType, catalogValue) ||
                Objects.equals(resourceType, menuValue)) {
            if (!Objects.equals(parentType, catalogValue)) {
                throw new ServiceException("上级菜单只能为目录类型");
            }
            return;
        }

        //按钮
        if (Objects.equals(resourceType, buttonValue)) {
            if (!Objects.equals(parentType, menuValue)) {
                throw new ServiceException("上级菜单只能为菜单类型");
            }
        }

        //API
        if (Objects.equals(resourceType, apiValue)) {
            EResourceType apiParentType = getResourceType(resource, apicatalogValue);
            if (!Objects.equals(apicatalogValue, apiParentType)) {
                throw new ServiceException("上级菜单只能为API菜单类型");
            }
        }
    }

    /**
     * 设置上级菜单类型
     */
    private EResourceType getResourceType(SysResourceRequestDto resource, EResourceType apicatalogValue) {
        //上级菜单类型
        EResourceType apiParentType = apicatalogValue;
        if (null != resource.getParent() && resource.getParent().getId() != 0) {
            SysResource parentResource = service.findById(resource.getParent().getId());
            apiParentType = parentResource.getType();
        }
        return apiParentType;
    }

    @ApiOperation(value = "获取所有权限")
    @PostMapping("permission")
    public ResponseEntity<ResponseBodyDto<List<SysResource>>> getPermissions() {
        List<SysResource> list = service.findAll();
        return returnSuccess(list);
    }
}
